#include "ThreadPool.hpp"
#include "WorkerThread.hpp"
#include <unistd.h>
#include <memory>

using std::unique_ptr;

namespace tp{

ThreadPool::ThreadPool(size_t tN,size_t qN)
:_threads()
,_threadNum(tN)
,_taskQue(qN)
,_queSize(qN)
,_isExit(false)
{

}
    
ThreadPool::~ThreadPool(){
    if(!_isExit){
        stop();
    }
}

void ThreadPool::start(){
    //01 创建子线程
    for(size_t i = 0; i < _threadNum; ++i){
        unique_ptr<Thread> subthread(new tp::WorkThread(*this));
        _threads.push_back(std::move(subthread));
    }

    //02 启动子线程
    for(auto & thread : _threads){
        thread->start();
    }
}

void ThreadPool::stop(){
    //01 判断任务队列是否还有任务

    //Q1：主线程执行太快，防止任务还没有执行完就退出
    //A1：主线程等待任务队列为空再回收
    while(!_taskQue.empty()){
        sleep(1);
    }

    //02 修改标志位
    _isExit = true;

    //Q2：任务执行完毕，但程序卡死无法退出？
    //A2：子线程执行快，主线程执行慢，子线程在跳出while(!_isExit)之前，
    //    主线程还没有修改标志位，任务队列为空，子线程pop之后进入睡眠
    //    需要将所有子线程唤醒
    _taskQue.wakeup();

    //03 回收子线程
    for(auto & thread : _threads){
        thread->join();
    }
}

void ThreadPool::addTask(tp::Task * ptask){
    //添加任务
    if(ptask){
        _taskQue.push(ptask);
    }
}

void ThreadPool::doTask(){
    //取任务
    while(!_isExit){
        Task * ptask = _taskQue.pop();
        //执行任务
        if(ptask){
            ptask->process();
        }
    }
}

}//end of namespace tp
